package ovm.management.load;

import ovm.entity.*;
import ovm.management.AbstractManager;

import javax.persistence.Query;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: Jokser
 * Date: 15.06.12
 * Time: 1:43
 * To change this template use File | Settings | File Templates.
 */

public class LoadManager extends AbstractManager {

    public static int SUBJECT_NOT_FOUND = -5;
    public static int PRACTICE_HOURS_EXCEED = -4;
    public static int LECTURE_HOURS_EXCEED = -3;
    public static int LAB_HOURS_EXCEED = -2;
    public static int EXAM_HOURS_EXCEED = -1;
    public static int LOADERS_NOT_FOUND = 1;

    private static LoadSubjectEntity getLoadSubjectEntity (SubjectEntity subject, StudyGroupEntity group, SemesterEntity semester) {
        Query query = em.createQuery("SELECT e FROM LoadSubjectEntity e " +
                "WHERE e.subject = :subject and e.studyGroup = :group and e.semester = :semester");
        query.setParameter("subject", subject);
        query.setParameter("group", group);
        query.setParameter("semester", semester);
        List<LoadSubjectEntity> list = query.getResultList();
        if (list.size() == 0) return null;
        return list.get(0);
    }

    private static List<LoadSubjectTeacherEntity> getLoadSubjectTeacherEntities (SubjectEntity subject, StudyGroupEntity group, SemesterEntity semester) {
        Query query = em.createQuery("SELECT e FROM LoadSubjectTeacherEntity e " +
                "WHERE e.subject = :subject and e.studyGroup = :group and e.semester = :semester");
        query.setParameter("subject", subject);
        query.setParameter("group", group);
        query.setParameter("semester", semester);
        return query.getResultList();
    }

    private static int checkOrAcceptLoad (LoadSubjectEntity entity, boolean check) {
        int lectureHours = entity.getLectureHours(),
                practiceHours = entity.getPracticeHours(),
                labHours = entity.getLabHours(),
                examHours = entity.getExamHours();

        List<LoadSubjectTeacherEntity> loadList = getLoadSubjectTeacherEntities(entity.getSubject(), entity.getStudyGroup(), entity.getSemester());

        for (LoadSubjectTeacherEntity loadEntity : loadList) {
            lectureHours -= loadEntity.getLectureHours();
            practiceHours -= loadEntity.getPracticeHours();
            labHours -= loadEntity.getLabHours();
            examHours -= loadEntity.getExamHours();
        }

        if (lectureHours < 0) return LECTURE_HOURS_EXCEED;
        if (practiceHours < 0) return PRACTICE_HOURS_EXCEED;
        if (labHours < 0) return LAB_HOURS_EXCEED;
        if (examHours < 0) return EXAM_HOURS_EXCEED;

        if (!check) {
            int allHours = lectureHours + practiceHours + labHours + examHours;
            if (allHours != 0) {
                LoadSubjectRemainEntity remainEntity = new LoadSubjectRemainEntity();
                remainEntity.setSubject(entity.getSubject());
                remainEntity.setStudyGroup(entity.getStudyGroup());
                remainEntity.setSemester(entity.getSemester());
                remainEntity.setLectureHours(lectureHours);
                remainEntity.setPracticeHours(practiceHours);
                remainEntity.setLabHours(labHours);
                remainEntity.setExamHours(examHours);
                remainEntity.setAllHours(allHours);
                em.persist(remainEntity);
            }
        }

        if (loadList.size() == 0) {
            return LOADERS_NOT_FOUND;
        }

        return 0;
    }

    public static int persistOrDeleteLoadSubjectEntity (LoadSubjectEntity entity, boolean delete) {
        if (!delete) {
            int checkResult = checkOrAcceptLoad(entity, true);
            if (checkResult < 0) return checkResult;
            try {
                em.getTransaction().begin();
                entity.setAllHours(entity.getExamHours() + entity.getLabHours() + entity.getLectureHours() + entity.getPracticeHours());

                em.persist(entity);
                recalculateLoad();

                em.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                em.getTransaction().rollback();
                em = emf.createEntityManager();
                return UNSUCCESSFUL;
            }
            return SUCCESSFUL;
        } else {
            int checkResult = checkOrAcceptLoad(entity, true);
            if (checkResult == LOADERS_NOT_FOUND) {
                try {
                    em.getTransaction().begin();

                    em.remove(entity);
                    recalculateLoad();

                    em.getTransaction().commit();
                } catch (Exception e) {
                    e.printStackTrace();
                    em.getTransaction().rollback();
                    em = emf.createEntityManager();
                    return UNSUCCESSFUL;
                }
                return SUCCESSFUL;
            } else {
                return UNSUCCESSFUL;
            }
        }
    }

    public static int persistOrDeleteLoadSubjectTeacherEntity (LoadSubjectTeacherEntity entity, boolean delete) {
        if (!delete) {
            LoadSubjectEntity loadEntity = getLoadSubjectEntity(entity.getSubject(), entity.getStudyGroup(), entity.getSemester());
            if (loadEntity == null) return SUBJECT_NOT_FOUND;
    
            int checkResult = checkOrAcceptLoad(loadEntity, true);
            if (checkResult < 0) return checkResult;
    
            try {
                em.getTransaction().begin();
                entity.setAllHours(entity.getExamHours() + entity.getLabHours() + entity.getLectureHours() + entity.getPracticeHours());
    
                em.persist(entity);
                recalculateLoad();
    
                em.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                em.getTransaction().rollback();
                em = emf.createEntityManager();
                return UNSUCCESSFUL;
            }
            return SUCCESSFUL;
        } else {
            try {
                em.getTransaction().begin();

                em.remove(entity);
                recalculateLoad();

                em.getTransaction().commit();
            } catch (Exception e) {
                e.printStackTrace();
                em.getTransaction().rollback();
                em = emf.createEntityManager();
                return UNSUCCESSFUL;
            }
            return SUCCESSFUL;
        }
    }


    private static int recalculateLoad () {
        try {
            Query query = em.createQuery("SELECT e FROM LoadSubjectEntity e");

            List<LoadSubjectEntity> subjectList = query.getResultList();
            for (LoadSubjectEntity entity : subjectList) {
                int checkResult = checkOrAcceptLoad(entity, true);
                if (checkResult < 0) {
                    return checkResult;
                }
            }

            System.out.println("Check successful");
            
            query = em.createQuery("SELECT e FROM LoadSubjectRemainEntity e");
            List<LoadSubjectRemainEntity> remainList = query.getResultList();
            for (LoadSubjectRemainEntity entity : remainList) {
                em.remove(entity);
            }

            System.out.println("All items has deleted");

            for (LoadSubjectEntity entity : subjectList) {
                checkOrAcceptLoad(entity, false);
            }

            System.out.println("Recalculate successful");

        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            em = emf.createEntityManager();
            return UNSUCCESSFUL;
        }

        return SUCCESSFUL;
    }
    
}
